package ch.ethz.fcl.metrobuzz.data.ltt.link;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ch.ethz.fcl.metrobuzz.data.ltt.TrajectoryGraph;
import ch.ethz.fcl.metrobuzz.data.ltt.node.LTTNode;
import ch.ethz.fcl.metrobuzz.render.techniques.cubic_hermite.CubicHermite;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;

/**
 * keeps a list of connected links without branches, used for construct smooth
 * lines
 * 
 * @author ZengWei
 * 
 */
public class LTTLongLink {
	private TrajectoryGraph trajGraph;
	private List<LTTLink> links;
	private Point2D[] pts = null;
	private Point2D[] spline = null;

	int pointSize = 100;

	public LTTLongLink(TrajectoryGraph trajGraph) {
		this.trajGraph = trajGraph;
		links = new ArrayList<LTTLink>();
	}

	public void addLink(LTTLink link) {
		links.add(link);
	}

	public void addLinkInFront(LTTLink link) {
		links.add(0, link);
	}

	public void generateSpline() {
		if (pts == null) {
			pts = new Point2D[links.size() + 1];
			LTTNode node = links.get(0).getFrom();
			int degree = node.toNode().getDegree();
			if (degree == 2 || degree == 4)
				pts[0] = node.toNode().toPoint();
			else {
				int linkIndex = node.getInterchange().getConnectedNodeIndex(
						links.get(0).getTo().getId());
				pts[0] = node.getInterchange().getConnectPoint(linkIndex, true);
			}
			for (int i = 0; i < links.size(); i++) {
				node = links.get(i).getTo();
				degree = node.toNode().getDegree();
				if (degree == 2 || degree == 4)
					pts[i + 1] = node.toNode().toPoint();
				else {
					int linkIndex = node.getInterchange()
							.getConnectedNodeIndex(
									links.get(i).getFrom().getId());
					pts[i + 1] = node.getInterchange().getConnectPoint(
							linkIndex, true);
				}
			}
			spline = CubicHermite.getCatmullRomSpline(pointSize, pts);
		}
	}

	public Point2D[] getSpline(LTTLink link) {
		if (!links.contains(link))
			return null;
		if (spline == null)
			generateSpline();

		int index = links.indexOf(link);
		if (index != links.size() - 1)
			return Arrays.copyOfRange(spline, index * pointSize, (index + 1)
					* pointSize + 1);
		else
			return Arrays.copyOfRange(spline, index * pointSize, (index + 1)
					* pointSize);
	}

	public TrajectoryGraph getTrajGraph() {
		return trajGraph;
	}

	public List<LTTLink> getLinks() {
		return links;
	}

	public Point2D[] getPassingPoints() {
		if (links.size() == 0)
			return null;
		if (pts == null) {
			generateSpline();
		}
		return pts;
	}

	@Override
	public String toString() {
		String output = "";
		for (LTTLink link : links)
			output += link.toString() + "->";
		return output;
	}
}
